package com.qcit.api.click

import android.app.Activity
import android.view.View
import androidx.fragment.app.Fragment
import com.qcit.annotation.click.EventType
import java.lang.reflect.InvocationHandler
import java.lang.reflect.Method
import java.lang.reflect.Proxy

object BindClickUtil {
    fun  BindClickEvent(aty:Activity){
        var handler = ListenerInvocationHandler<Activity>()
        handler.target = aty
        var clz = aty.javaClass
        bindEvent(clz,handler)
    }

    fun  BindClickEvent(fag:Fragment){
        var handler = ListenerInvocationHandler<Fragment>()
        handler.target = fag
        var clz = fag.javaClass
        bindEvent(clz,handler)
    }
    private fun bindEvent(clz: Class<*>,handler:ListenerInvocationHandler<*>) {
        val declaredMethods = clz.declaredMethods //获取页面class类所有的方法对象
        for (method in declaredMethods){
            //获得方法上的所有注解
            //一个方法可能会有多个注解
            val annotations = method.annotations
            if (null != annotations && annotations.size > 0){
                //遍历注解
                annotations.forEach {
                    //获取注解类型找到目标注解
                    //注解类型 @onClick / @onLongClick
                    val annotationType = it.javaClass
                    if (annotationType.isAnnotationPresent(EventType::class.java)){
                        val eventType = annotationType.getAnnotation(EventType::class.java)
                        //获取需要实现的接口
                        val listenerTypeClz = Class.forName(eventType.listenerType)
                        //获取设置接口的方法
                        //setOnClickListener
                        var funSetting = eventType.listenerSetting
                        //获取注解 中的控件id结合 @onClick({R.id.xxx , R.id.XXX})
                        val declaredMethod = annotationType.getDeclaredMethod("value")
                        declaredMethod.isAccessible = true
                        val ids = declaredMethod.invoke(it) as IntArray
                        handler.method = declaredMethod
                        val newProxyInstance = Proxy.newProxyInstance(
                            listenerTypeClz.classLoader,
                            arrayOf(listenerTypeClz),
                            handler
                        )
                        ids.forEach {
                            var view:View? = null
                            if (handler.target is Activity){
                                view = (handler.target as Activity).findViewById<View>(it)
                            } else{
                                view = (handler.target as Fragment).activity!!.findViewById<View>(it)
                            }
                            val viewSetting = view.javaClass.getMethod(funSetting, listenerTypeClz)
                            //setOnClickListener
                            viewSetting.invoke(view,newProxyInstance)
                        }
                    }
                }
            }
        }
    }
    class ListenerInvocationHandler<T>: InvocationHandler {
        var method: Method? = null
        var target: T? = null

        @Throws(Throwable::class)
        override fun invoke(proxy: Any?, method: Method?, args: Array<Any?>): Any? {
            return this.method!!.invoke(target, *args)
        }
    }
}